package com.arashivision.airlive;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Trace;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import com.arashivision.algorithm.Offset;
import com.arashivision.extradata.ARObject;
import com.arashivision.insta360.arutils.source.ISource;
import com.arashivision.insta360.arutils.source.SourceFactory;
import com.arashivision.insta360.export.exporter.ARComposerConfig;
import com.arashivision.insta360.export.services.ExportManager;
import com.arashivision.insta360.export.services.OnExportListener;
import com.arashivision.insta360.export.services.Request;
import com.arashivision.insta360.sdk.render.controller.GestureController;
import com.arashivision.insta360.sdk.render.controller.HeadTrackerController;
import com.arashivision.insta360.sdk.render.controller.gyro.CImageGyroController;
import com.arashivision.insta360.sdk.render.controller.gyro.VideoAntiShakeController;
import com.arashivision.insta360.sdk.render.player.IPlayerFactory;
import com.arashivision.insta360.sdk.render.player.PlayerDelegate;
import com.arashivision.insta360.sdk.render.renderer.Insta360PanoRenderer;
import com.arashivision.insta360.sdk.render.renderer.model.RenderModel;
import com.arashivision.insta360.sdk.render.renderer.model.SphericalModel;
import com.arashivision.insta360.sdk.render.renderer.model.SphericalStitchModel;
import com.arashivision.insta360.sdk.render.renderer.model.sticker.StickerFactory;
import com.arashivision.insta360.sdk.render.renderer.model.sticker.StickerInfo;
import com.arashivision.insta360.sdk.render.renderer.screen.SingleScreen;
import com.arashivision.insta360.sdk.render.renderer.strategy.FishEyeStrategy;
import com.arashivision.insta360.sdk.render.view.PanoramaView;

import org.rajawali3d.materials.textures.ISurfacePlayer;
import org.rajawali3d.math.Matrix4;
import org.rajawali3d.math.vector.Vector3;

import java.net.URLDecoder;

public class PlayActivity extends AppCompatActivity {

    private static final String TAG = "PlayActivity";
    private PlayerDelegate mPlayerDelegate;
    private Insta360PanoRenderer mRenderer;
    private PanoramaView mPanoramaView;
    private RenderModel mRenderModel;
    private HeadTrackerController mHeadTrackerController;
    private GestureController mGestureController;
    private VideoAntiShakeController mVideoAntiShakeController;

//    private String mUrl = "/storage/emulated/0/one_demo/test_arobject.mp4";
    private String mUrl = "/storage/emulated/0/one_demo/test_pano.mp4";

    private String mPicUrl = "/storage/emulated/0/one_demo/test.jpg";
    private String outputPic = "/storage/emulated/0/one_demo/demo.jpg";

    private int mPicWidth;
    private int mPicHeight;

    private int test_times = 0;
    private boolean mVideoRenderStitch = false;
    private ExportManager mExportManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_play);

        mExportManager = new ExportManager(this);
    }

    @Override
    public void onResume() {
        super.onResume();
        mExportManager.register();
    }

    @Override
    public void onPause() {
        super.onPause();
        mExportManager.unregister();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private void startTrace()
    {
        Trace.beginSection("TestARPlayer");
    }

    private void endTrace()
    {
        Trace.endSection();
    }

    private void createPicResources()
    {
        destroyResources();
        mRenderer = new Insta360PanoRenderer(getApplicationContext());
        //render model
        mRenderModel = new SphericalStitchModel(mRenderer.getId());
        //
        mRenderer.init(new FishEyeStrategy(), new IPlayerFactory.DefaultPlayerFactory(),
                mRenderModel, new SingleScreen());

        mRenderer.getRenderModelScene().setBackgroundColor(100);
        //surface view
        mPanoramaView = new PanoramaView(getApplicationContext());
        mPanoramaView.setFrameRate(60.0f);
        mPanoramaView.setRenderMode(PanoramaView.RENDERMODE_WHEN_DIRTY);
        mPanoramaView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        mPanoramaView.setRenderer(mRenderer);

        //player
        mPlayerDelegate = mRenderer.getTextureHolder().getPlayerDelegate();
        mPlayerDelegate.setOnPreparedListener(new ISurfacePlayer.OnPreparedListener() {
            @Override
            public void onPrepared(ISurfacePlayer iSurfacePlayer) {
                Log.d(TAG,"onPrepared");
            }
        });

        //gesture
        mGestureController = new GestureController(this , mRenderModel.getCamera());
        mGestureController.setOnGestureListener(new GestureDetector.OnGestureListener()
        {
            @Override
            public boolean onDown(MotionEvent e)
            {
                Log.d(TAG,"onDown");
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e)
            {
                Log.d(TAG,"onShowPress");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e)
            {
                Log.d(TAG,"onSingleTapUp");
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
            {
                Log.d(TAG,"onScroll");
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e)
            {
                Log.d(TAG,"onLongPress");
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
            {
                Log.d(TAG,"onFling");
                return false;
            }
        });
        mGestureController.setHolders(mRenderModel.getLayerAt(0));
        mGestureController.setEnabled(true);
        mRenderer.getControllerManager().addController(GestureController.class.getSimpleName(), mGestureController);

        ARObject mArObject =  ARObject.create(mPicUrl);
        CImageGyroController mCImage = new CImageGyroController(mArObject.getGyro());
        mCImage.getGyroQuaternion().toRotationMatrix();

        Matrix4 postMatrix = mCImage.getGyroQuaternion().toRotationMatrix();
        mRenderModel.setPostMatrix(postMatrix);

        //apply
        FrameLayout layout = (FrameLayout)findViewById(R.id.layout_loader_container);
        layout.addView(mPanoramaView);
    }

    private void createResources() {
        destroyResources();
        //render
        mRenderer = new Insta360PanoRenderer(getApplicationContext());
        //render model
        if(mVideoRenderStitch)
        {
            mRenderModel = new SphericalStitchModel(mRenderer.getId());
        }
        else
        {
            mRenderModel = new SphericalModel(mRenderer.getId());
        }
        mRenderer.init(new FishEyeStrategy(), new IPlayerFactory.DefaultPlayerFactory(), mRenderModel, new SingleScreen());
        mRenderer.getRenderModelScene().setBackgroundColor(100);
        //surface view
        mPanoramaView = new PanoramaView(getApplicationContext());
        mPanoramaView.setFrameRate(60.0f);
        mPanoramaView.setRenderMode(PanoramaView.RENDERMODE_WHEN_DIRTY);
        mPanoramaView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        mPanoramaView.setRenderer(mRenderer);

        //player
        mPlayerDelegate = mRenderer.getTextureHolder().getPlayerDelegate();
        mPlayerDelegate.setOnPreparedListener(new ISurfacePlayer.OnPreparedListener() {
            @Override
            public void onPrepared(ISurfacePlayer iSurfacePlayer) {
                Log.d(TAG,"onPrepared");
                mRenderer.getTextureHolder().setForceUpdateTexture(true);
                iSurfacePlayer.start();
                iSurfacePlayer.setLooping(true);
            }
        });

        //head tracker
//        mHeadTrackerController = new HeadTrackerController(this);
//        mHeadTrackerController.setHolders(mRenderModel);
//        mHeadTrackerController.setEnabled(true);
//        mRenderer.getControllerManager().addController(HeadTrackerController.class.getSimpleName(), mHeadTrackerController);

        //gesture
        mGestureController = new GestureController(this , mRenderModel.getCamera());
        mGestureController.setOnGestureListener(new GestureDetector.OnGestureListener()
        {
            @Override
            public boolean onDown(MotionEvent e)
            {
                Log.d(TAG,"onDown");
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e)
            {
                Log.d(TAG,"onShowPress");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e)
            {
                Log.d(TAG,"onSingleTapUp");
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
            {
                Log.d(TAG,"onScroll");
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e)
            {
                Log.d(TAG,"onLongPress");
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
            {
                Log.d(TAG,"onFling");
                return false;
            }
        });
        mGestureController.setHolders(mRenderModel.getLayerAt(0));
        mGestureController.setEnabled(true);
        mRenderer.getControllerManager().addController(GestureController.class.getSimpleName(), mGestureController);

        //video anti shake
        if(mVideoRenderStitch)
        {
            mVideoAntiShakeController = new VideoAntiShakeController(mUrl, mPlayerDelegate.getPlayer());
            mVideoAntiShakeController.setHolders(mRenderModel.getLayerAt(1));
            mVideoAntiShakeController.setEnabled(true);
            mRenderer.getControllerManager().addController(VideoAntiShakeController.class.getSimpleName(), mVideoAntiShakeController);
        }

        //apply
        FrameLayout layout = (FrameLayout)findViewById(R.id.layout_loader_container);
        layout.addView(mPanoramaView);
    }

    private void destroyResources() {
        if(mPlayerDelegate != null)
        {
            if (mRenderer != null) {
                mRenderer.onDestroy();
                mRenderer = null;
            }
            FrameLayout layout = (FrameLayout)findViewById(R.id.layout_loader_container);
            layout.removeView(mPanoramaView);

            mPanoramaView = null;
            mPlayerDelegate = null;
        }
    }

    private ProgressDialog mProgressDialog;
    private int type;

    public static final int IMAGE_PANO = 101;
    public static final int IMAGE_LITTLE_STAR = 102;
    public static final int VIDEO_WIDTH_ANGLE = 103;
    public static final int VIDEO_PANO = 104;

    public static final int RATIO_1_1 = 1;
    public static final int RATIO_4_3 = 2;
    public static final int RATIO_16_9 = 3;

    public synchronized void showProgressDialog(String str){
        if(mProgressDialog != null){
            mProgressDialog.dismiss();
            mProgressDialog = null;
        }
        mProgressDialog = ProgressDialog.show(PlayActivity.this, "Tip", str);
    }


    public synchronized void hideProgressDialog(){
        if(mProgressDialog != null){
            try{
                mProgressDialog.dismiss();
                mProgressDialog = null;
            }catch (Throwable e){}
        }
    }


    public void onStartExport(View mView)
    {
        if(mPicWidth == 0 || mPicHeight == 0)
        {
            Log.e(TAG,"please play pic first");
            return;
        }
        showProgressDialog("convert...");
        Log.d(TAG,"onStartExport start");

        try {
            outputPic = URLDecoder.decode(outputPic , "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        type = IMAGE_PANO;
        Request request;
        switch (type){
//            case IMAGE_LITTLE_STAR:
//                request = new Request(ARComposerConfig.TYPE_THUMBNAIL_LITTLESTAR);
//                break;
            case IMAGE_PANO:
                request = new Request(ARComposerConfig.TYPE_THUMBNAIL_STITCH);
                break;
//            case VIDEO_PANO:
//                request = new Request(ARComposerConfig.TYPE_VIDEO_STITCH);
//                break;
//            case VIDEO_WIDTH_ANGLE:
//                request = new Request(ARComposerConfig.TYPE_VIDEO_FISHEYE);
//                break;
            default:
                request = new Request(ARComposerConfig.TYPE_COMPOSER);
                break;
        }
        request.setInput(mPicUrl);
        request.setOutput(outputPic);
//        if (type == IMAGE_LITTLE_STAR || type == VIDEO_WIDTH_ANGLE){
//            request.setHeight(mPicHeight);
//            request.setWidth(mPicWidth);
//        }else {
//            request.setHeight(0);
//        }
        request.setHeight(mPicHeight);
        request.setWidth(mPicWidth);

        request.setQuality(100);

        if (type == IMAGE_LITTLE_STAR || type == VIDEO_WIDTH_ANGLE) {
            request.setFov(mRenderer.getRenderModel().getCamera().getFieldOfView());
            request.setDistance(mRenderer.getRenderModel().getCamera().getZ());
        }

        StickerInfo stickerInfo = StickerFactory.createStickerInfo( R.mipmap.logo_black_zh , 50, Vector3.X,90 , 1.f,true);
        request.setSticker(stickerInfo);

        ARObject arObject = ARObject.create(request.getInput());

        if(arObject != null){
            Log.d(TAG,"gyro calibrate");
            CImageGyroController cImageGyroController = new CImageGyroController(arObject.getGyro());
            //陀螺仪校准
            Matrix4 postMatrix = cImageGyroController.getGyroQuaternion().toRotationMatrix();
            request.setPostMatrix(postMatrix);
        }

        mExportManager.setOnExportListener(new OnExportListener() {
            @Override
            public void onComplete(String id) {
                Log.d(TAG,"export onComplete");
                hideProgressDialog();
            }

            @Override
            public void onCancel(String id) {
                hideProgressDialog();
            }

            @Override
            public void onError(String id, int code) {
                hideProgressDialog();
                Log.e(TAG,"export error " + code);
            }

            @Override
            public void onProgress(String id, int progress) {
                Log.e(TAG,"export onProgress " + progress);
            }

            @Override
            public void onFileSizeChanged(String id, String path , long fileSize) {

            }
        });
        mExportManager.enqueue(request);
    }

    public void OnStartPicClick(View view)
    {
        startTrace();
        Log.d(TAG," mPicUrl " + mPicUrl);

        createPicResources();

        final ISource source = SourceFactory.create(mPicUrl);

        mPicWidth = source.getWidth();
        mPicHeight = source.getHeight();

        Log.d(TAG," mPicUrl " + mPicUrl + " w " +
                mPicWidth + " h " + mPicHeight);

        mRenderer.getSourceManager().start(source);
        endTrace();
    }

    public void OnStartVideoClick(View view) {
        Log.d(TAG,"mUrl " + mUrl);
        startTrace();
        createResources();
        final ISource source = SourceFactory.create(mUrl);
        if (source.hasOffset() && source.getWidth() == source.getHeight() * 4) {
            //update offset
            String offset = Offset.normal2One120fps(source.getOffset());
            source.updateOffset(offset);
        }
        mRenderer.getSourceManager().start(source);
        endTrace();
    }

//    public void OnTestClick(View view) {
//        if (!mSampling) {
//            mSamplingManager.clearAnimationStates();
//            mSampling = true;
//            Button button  = (Button)findViewById(R.id.button);
//            button.setText("Sampling...");
//        } else {
//            mSampling = false;
//            Button button  = (Button)findViewById(R.id.button);
//            button.setText("Applying...");
//        }
//    }

    public void OnStopClick(View view) {
        destroyResources();
    }
}
